package both.map.mapModel;

/**
 * The standard implementation of cells. 
 * Objects of this class store the cell's content, and update it.
 * Whenever the cell is updated, the "updated" flag is set to true,
 * and when the content of the cell is accessed, the flag is set to
 * false again. 
 * 
 * It is assumed that the ModelCell object exists in an environment 
 * where it only has one direct client object (presumably a MapModel),
 * and that the MapModel handles how to send out those updates. If 
 * it turns out that ModelCell needs to report updates to more than 
 * one client object at a time, then this will need to be refactored.
 * 
 * @author jdl
 */
public abstract class ModelCell {

	/*  flags whether the cell's content has been updated since the last
	 *  time its content was accessed.  
	 */
	private boolean updated;
	
	// flag to record whether this cell is part of an update map, or part of a map
	private final boolean partOfUpdate;
	
	/**
	 * build a new ModelCell
	 * @param partOfUpdate should be true
	 */
	public ModelCell(boolean partOfUpdate)
	{
		this.partOfUpdate = partOfUpdate;
	}
	
	public boolean isPartOfUpdate()
	{
		return partOfUpdate;
	}

	/**
	 * record that this cell has an updated which has not yet
	 * been sent out.
	 */
	protected void flagForUpdate() 
	{
		updated = true;
	}

	/**
	 * @return true if the cell has content which has been updated 
	 * since the last time the content was sent out
	 */
	public boolean hasBeenUpdated() 
	{		
		return updated;
	}
	
	/**
	 * reset the updated flag, by indicating that the flagged update has
	 * been grabbed
	 */
	protected void resetUpdate()
	{
		updated = false;
	}
	
	/**
	 * store an update for the future. Flags the cell for an update, even if 
	 * the update has already been passed.
	 */
	public void storeUpdate()
	{
		flagForUpdate();
	}
	
	/**
	 * @return the updated contents of this cell
	 */
	public abstract ModelCell grabUpdate();

	/**
	 * Apply an update cell to this one
	 * @param updateCell the cell which is to be used updating this one
	 * @throws IllegalArgumentException if the updateCell is of wrong type
	 */
	public abstract void applyUpdate(ModelCell updateCell)
		throws IllegalArgumentException;
}
